package com.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * HTTP请求处理
 * 
 * @author JJF
 * 
 */
public class HttpsUtls {
    private final static Logger logger = LoggerFactory.getLogger(HttpsUtls.class);
    private static final Charset UTF_8 = Charset.forName("UTF-8");
    public static final String POST = "POST";
    public static final String GET = "GET";
    public static final int TIMEOUT = 30000;

    static {
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL"); // TLS或SSL
            sslContext.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() }, new SecureRandom());
        } catch (GeneralSecurityException e) {
        }
        if (sslContext != null) {
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        }
        HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());

    }


    /**
     * GET 请求
     * 
     * @param serverUrl
     * @param params
     * @return
     */
    public static String get(String serverUrl, Map<String, String> params) {
        return executeGet(serverUrl, params, TIMEOUT);
    }

    /**
     * POST 请求
     * 
     * @param serverUrl
     * @param params
     * @return
     */
    public static String post(String serverUrl, HashMap<String, String> params) {
        return execute(serverUrl, params, TIMEOUT);
    }

    /**
     * 发送HTTP请求
     * 
     * @param serverUrl
     * @param method
     * @param params
     * @param timeout
     * @return
     */
    public static String execute(String serverUrl, HashMap<String, String> params, int timeout) {
        HttpURLConnection conn = null;
        OutputStreamWriter osw = null;
        BufferedReader br = null;
        try {
            // 发送请求
            URL url = new URL(serverUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            conn.setRequestMethod("POST");
            conn.setUseCaches(false);
            conn.setDoOutput(true);
            conn.setReadTimeout(timeout);
            conn.setConnectTimeout(timeout);
            logger.info("[HTTP SERVICE] connection success,URL: {}", serverUrl);

            // 构建请求参数
            StringBuilder sbParam = new StringBuilder();
            if (MapUtils.isNotEmpty(params)) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    sbParam.append(entry.getKey());
                    sbParam.append("=");
                    sbParam.append(entry.getValue());
                    sbParam.append("&");
                }
            }
            logger.debug("[HTTP SERVICE] request params：{}", sbParam);

            // 获得输出流
            osw = new OutputStreamWriter(conn.getOutputStream(), UTF_8);
            osw.write(sbParam.toString());
            osw.flush();
            osw.close();

            int responseCode = conn.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                logger.error("[HTTP SERVICE] responseCode：{}", responseCode);
                return StringUtils.EMPTY;
            }
            // 取得返回信息
            br = new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF_8));
            String line;
            StringBuilder result = new StringBuilder();
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
            // JSON处理
            return result.toString();
        } catch (Exception e) {
            logger.error("[HTTP SERVICE] Exception", e);
        } finally {
            if (osw != null) {
                try {
                    osw.close();
                } catch (Exception e) {
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                }
            }
            if (conn != null) {
                try {
                    conn.disconnect();
                } catch (Exception e) {
                }
            }
        }

        return StringUtils.EMPTY;
    }
    
    
    /**
     * 发送HTTP请求
     * 
     * @param serverUrl
     * @param method
     * @param params
     * @param timeout
     * @return
     */
    public static String executeGet(String serverUrl, Map<String, String> params, int timeout) {
        HttpURLConnection conn = null;
        BufferedReader br = null;
        try {
            // 构建请求参数
            StringBuilder sbParam = new StringBuilder();
            if (MapUtils.isNotEmpty(params)) {
                sbParam.append("?");
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    sbParam.append(entry.getKey());
                    sbParam.append("=");
                    sbParam.append(entry.getValue());
                    sbParam.append("&");
                }
                serverUrl += sbParam.toString();
            }
            // 发送请求
            URL url = new URL(serverUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestMethod("GET");
            conn.setUseCaches(false);
            conn.setDoOutput(true);
            conn.setReadTimeout(timeout);
            conn.setConnectTimeout(timeout);
            logger.info("[HTTP SERVICE] connection success,URL: {}", serverUrl);

            int responseCode = conn.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                logger.error("[HTTP SERVICE] responseCode：{}", responseCode);
                return StringUtils.EMPTY;
            }
            // 取得返回信息
            br = new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF_8));
            String line;
            StringBuilder result = new StringBuilder();
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
            // JSON处理
            return result.toString();
        } catch (Exception e) {
            logger.error("[HTTP SERVICE] Exception", e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                }
            }
            if (conn != null) {
                try {
                    conn.disconnect();
                } catch (Exception e) {
                }
            }
        }

        return StringUtils.EMPTY;
    }
    
    /**
     * 推送json数据
     * 
     * @param serverUrl
     * @param requestBody
     * @return
     */
    public static String postJson(String serverUrl, Map<String, String> params, String requestBody) {
        return executeJson(serverUrl, params, requestBody, null, TIMEOUT);
    }

    /**
     * 推送json数据到服务器
     * 
     * @param serverUrl
     * @param requestBody
     * @param headers
     * @param timeout
     * @return
     */
    public static String executeJson(String serverUrl, Map<String, String> params, String requestBody, HashMap<String, String> headers, int timeout) {
        HttpURLConnection conn = null;
        OutputStreamWriter osw = null;
        BufferedReader br = null;
        try {
            // 构建请求参数
            if (MapUtils.isNotEmpty(params)) {
                StringBuilder sbParam = new StringBuilder();
                sbParam.append("?");
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    sbParam.append(entry.getKey());
                    sbParam.append("=");
                    sbParam.append(entry.getValue());
                    sbParam.append("&");
                }
                serverUrl += sbParam.toString();
            }
            // 发送请求
            URL url = new URL(serverUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestMethod("POST");
            conn.setUseCaches(false);
            conn.setDoOutput(true);
            conn.setReadTimeout(timeout);
            conn.setConnectTimeout(timeout);

            if (MapUtils.isNotEmpty(headers)) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            logger.info("[HTTP SERVICE] connection success,URL: {}", serverUrl);

            // 获得输出流
            osw = new OutputStreamWriter(conn.getOutputStream(), UTF_8);
            osw.write(requestBody);
            osw.flush();
            osw.close();

            // 获取状态码
            int responseCode = conn.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                logger.error("[HTTP SERVICE] response status = {}", responseCode);
                return StringUtils.EMPTY;
            }

            // 取得返回信息
            br = new BufferedReader(new InputStreamReader(conn.getInputStream(), UTF_8));
            String line;
            StringBuilder result = new StringBuilder();
            while ((line = br.readLine()) != null) {
                result.append(line);
            }
            logger.debug("[HTTP SERVICE] response {}", result.toString());

            // JSON处理
            return result.toString();
        } catch (Exception e) {
            logger.error("[HTTP SERVICE] Exception", e);
        } finally {
            if (osw != null) {
                try {
                    osw.close();
                } catch (Exception e) {
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                }
            }
            if (conn != null) {
                try {
                    conn.disconnect();
                } catch (Exception e) {
                }
            }
        }

        return StringUtils.EMPTY;
    }

}

/**
 * 自定义的认证管理类
 * 
 * @author JJF
 *
 */
class MyX509TrustManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

class MyHostnameVerifier implements HostnameVerifier {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
}
